package com.waijiaojun.tpo.service.weixin;

import com.waijiaojun.tpo.comm.MyPage;
import com.waijiaojun.tpo.comm.PayStatus;
import com.waijiaojun.tpo.entity.GoodsOrder;
import com.waijiaojun.tpo.entity.weixin.WeixinH5payNotify;
import com.waijiaojun.tpo.entity.weixin.WeixinPublic;
import com.waijiaojun.tpo.repository.GoodsOrderDao;
import com.waijiaojun.tpo.repository.weixin.WeixinH5payNotifyDao;
import com.waijiaojun.tpo.rest.RestServerException;
import com.waijiaojun.tpo.utils.*;
import com.waijiaojun.tpo.vo.wx.OrderPaySuccessTemplateMsg;
import com.waijiaojun.tpo.vo.wx.response.PayNotifyResponse;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 
 * 
 * @author Peter
 */
// Spring Service Bean的标识.
@Component
public class WeixinH5payNotifyService {

	private static final String _COLOR_FAIL = "#FF0000";

	private static final String _COLOR_SUCCESS = "#329933";

	private static final String OK = "OK";

	private static final String SUCCESS = "SUCCESS";

	private static Logger logger = LoggerFactory.getLogger(WeixinH5payNotifyService.class);
	
	@Autowired
	private WeixinPublicService weixinPublicService;
	
	@Autowired
	private WeixinAccessTokenService weixinAccessTokenService;

	@Autowired
	private WeixinH5payNotifyDao weixinH5payNotifyDao;
	
	@Autowired
	private GoodsOrderDao goodsOrderDao;

	public WeixinH5payNotify getById(Long id) {
		return weixinH5payNotifyDao.getById(id);
	}

	public List<WeixinH5payNotify> getAll() {
		return weixinH5payNotifyDao.getAll();
	}

	/**
	 * 分页查询
	 *
	 * @param pageSize
	 * @return
	 */
	public MyPage<WeixinH5payNotify> searchPage(WeixinH5payNotify weixinH5payNotify, int currentPage, int pageSize) {
		MyPage<WeixinH5payNotify> myPage = new MyPage<WeixinH5payNotify>();

		Long count = weixinH5payNotifyDao.searchCount(weixinH5payNotify);

		int pageStart = (currentPage - 1) < 0 ? 0 : (currentPage - 1) * pageSize;
		List<WeixinH5payNotify> list = weixinH5payNotifyDao.searchPage(weixinH5payNotify, pageStart, pageSize);

		myPage.setCount(count);
		myPage.setContent(list);

		return myPage;
	}

	public void save(WeixinH5payNotify weixinH5payNotify) {
		weixinH5payNotifyDao.save(weixinH5payNotify);
	}

	public void update(WeixinH5payNotify weixinH5payNotify) {
		weixinH5payNotifyDao.update(weixinH5payNotify);
	}

	/**
	 * 软删除
	 */
	public void delete(Long id) {
		weixinH5payNotifyDao.delete(id);
	}

	
	/**
	 * 通知频率为15/15/30/180/1800/1800/1800/1800/3600，单位：秒<br/>
	 * 
	 * 由于存在重新发送后台通知的情况，因此同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
		推荐的做法是，当收到通知进行处理时，首先检查对应业务数据的状态，判断该通知是否已经处理过，
		如果没有处理过再进行处理，如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前，要采用数据锁进行并发控制，以避免函数重入造成的数据混乱。
	 * @param weixinH5payNotifyXml
	 * @return
	 * 需要微信服务器再次发出通知
	 */
	public synchronized PayNotifyResponse processPayNotify(String weixinH5payNotifyXml){
		
		PayNotifyResponse resp = new PayNotifyResponse();
		resp.setReturn_code(SUCCESS);
		resp.setReturn_msg(OK);

		Map<String, String> resultMap = null;
		try {
			resultMap = XmlUtil.toMap(weixinH5payNotifyXml);
		} catch (DocumentException e) {
			logger.error(e.getMessage(), e);
			throw new RestServerException("解析微信支付回调xml出错");
		}

		WeixinH5payNotify weixinH5payNotify = XmlUtil.fromXml(weixinH5payNotifyXml, WeixinH5payNotify.class);

		//幂等处理：是否已成功处理过该订单的通知，直接返回，否则执行处理逻辑
//		if (isNotified(weixinH5payNotify)) {
//			return resp;
//		}

        //网络数据正确性校验，如果失败说明有人恶意修改数据，需要
		//    1. 记录日志，发出报警，人工定位原因，给出业务解决方案；
		//    2. 返回FAIL，告知微信服务器重新发起订单确认
		validateSign(resultMap, weixinH5payNotify);

		if (SUCCESS.equals(weixinH5payNotify.getReturnCode()) && SUCCESS.equals(weixinH5payNotify.getResultCode())) {
			//支付成功，修改订单状态为“支付成功”、支付状态为“支付成功”
			goodsOrderDao.updatePayStatus(weixinH5payNotify.getOutTradeNo(), PayStatus.PAY_SUCCESS);

		} else {
			//修改订单支付状态为：2：支付失败
			goodsOrderDao.updatePayStatus(weixinH5payNotify.getOutTradeNo(), PayStatus.PAY_FAIL);

		}

		return resp;
	}

	private void validateSign(Map<String, String> resultMap, WeixinH5payNotify weixinH5payNotify) {
		WeixinPublic weixinPublic = weixinPublicService.getGlobleWeixinPublic();
		String sign = weixinH5payNotify.getSign();

		String mySign = WeixinPaySignUtils.payUniSign(resultMap, weixinPublic.getPayApiKey());
		weixinH5payNotify.setMySign(mySign);
		weixinH5payNotify.setCreateDate(new Date());

		//1. 记录日志 保存到数据库
		weixinH5payNotifyDao.save(weixinH5payNotify);
		if (!mySign.equals(sign)) {
			// 2. 返回FAIL，告知微信服务器重新发起订单确认
			logger.error("数据完整性校验：微信【支付结果通知】接口返回数据被篡改：mySign:" + mySign + ",sign:" + sign);
			throw new RestServerException("通讯错误");
		}
	}

	/**
	 * 发送模板消息【订单支付成功】
	 * @param tmsg
	 */
	private void sendTemplateMsg(OrderPaySuccessTemplateMsg tmsg) {
		String requestJson = JsonUtil.toJson(tmsg);
		String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+weixinAccessTokenService.getAccessToken();

		String responseJson = "";
		try {
			responseJson = HttpUtil.httpPost(url, requestJson);
		} catch (Exception e) {
			logger.error("模板消息发送失败", e);
			//throw new ServerException(Error._40002, Error._40002_MSG);
		}
	}

	/**
	 * 是否已经处理过订单通知
	 * @param weixinH5payNotify
	 * @return
	 */
	private boolean isNotified(WeixinH5payNotify weixinH5payNotify) {
		boolean result = false;
		List<WeixinH5payNotify> list= weixinH5payNotifyDao.getByOrderCode(weixinH5payNotify.getOutTradeNo());
		if(list!=null && list.size()>0){
			for (WeixinH5payNotify notify : list) {
				//如果通知签名一样，说明已经成功接收了订单通知。
				if(notify.getSign().equals(notify.getMySign())){
					result = true;
				}
			}
		}
		
		return result;
	}
}
